package cn.jbt.api.admin.service.impl;

import cn.jbt.api.admin.entity.QSysPost;
import cn.jbt.api.admin.entity.QSysUserPost;
import cn.jbt.api.admin.entity.SysPost;
import cn.jbt.api.admin.filter.LoginInfoAccessContext;
import cn.jbt.api.admin.repository.SysPostRepository;
import cn.jbt.api.admin.repository.SysUserPostRepository;
import cn.jbt.api.admin.service.ISysPostService;
import cn.jbt.common.PageQryParam;
import cn.jbt.common.PageQryResult;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Service
@Slf4j
@AllArgsConstructor
public class SysPostServiceImpl implements ISysPostService {

    private final JPAQueryFactory jpaQueryFactory;
    private final SysPostRepository sysPostRepository;
    private final SysUserPostRepository sysUserPostRepository;

    @Override
    public PageQryResult<SysPost> getAllByPage(PageQryParam<SysPost> pageQryParam) {
        SysPost qParam = pageQryParam.getParam();
        QSysPost qSysPost = QSysPost.sysPost;

        Predicate predicate = qSysPost.isNotNull().or(qSysPost.isNull());
        if (null != qParam) {
            if (!StringUtils.isEmpty(qParam.getPostName())) {
                predicate = ExpressionUtils.and(predicate,
                        qSysPost.postName.contains(qParam.getPostName()));
            }
            if (!StringUtils.isEmpty(qParam.getPostCode())) {
                predicate = ExpressionUtils.and(predicate,
                        qSysPost.postCode.contains(qParam.getPostCode()));
            }
            if (null != qParam.getStatus()) {
                predicate = ExpressionUtils.and(predicate,
                        qSysPost.status.eq(qParam.getStatus()));
            }
        }

        List<SysPost> list = jpaQueryFactory.select(qSysPost)
                .from(qSysPost)
                .where(predicate)
                .orderBy(qSysPost.orderby.asc(), qSysPost.id.desc())
                .offset((pageQryParam.getPage() - 1) * pageQryParam.getSize())
                .limit(pageQryParam.getSize())
                .fetch();

        long total = Optional.ofNullable(jpaQueryFactory.select(qSysPost.id.count())
                .from(qSysPost)
                .where(predicate)
                .fetchOne()
        ).orElse(0L);

        return new PageQryResult<>(list, total);
    }

    @Override
    public List<SysPost> getAll(SysPost sysPost) {
        QSysPost qSysPost = QSysPost.sysPost;

        Predicate predicate = qSysPost.isNotNull().or(qSysPost.isNull());
        if (null != sysPost) {
            if (!StringUtils.isEmpty(sysPost.getPostName())) {
                predicate = ExpressionUtils.and(predicate,
                        qSysPost.postName.contains(sysPost.getPostName()));
            }
            if (!StringUtils.isEmpty(sysPost.getPostCode())) {
                predicate = ExpressionUtils.and(predicate,
                        qSysPost.postCode.contains(sysPost.getPostCode()));
            }
            if (null != sysPost.getStatus()) {
                predicate = ExpressionUtils.and(predicate,
                        qSysPost.status.eq(sysPost.getStatus()));
            }
        }

        return jpaQueryFactory.select(qSysPost)
                .from(qSysPost)
                .where(predicate).orderBy(qSysPost.id.desc())
                .fetch();
    }

    @Override
    public SysPost add(SysPost sysPost) {
        if (null != sysPostRepository.findFirstByPostCode(sysPost.getPostCode())) {
            throw new RuntimeException("岗位编号已存在");
        }

        sysPost.setCreateBy(LoginInfoAccessContext.getLoginInfo().getNickname());
        sysPost.setUpdateBy(sysPost.getCreateBy());
        return sysPostRepository.save(sysPost);
    }

    @Override
    public SysPost edit(SysPost sysPost) {
        SysPost newSysPost = sysPostRepository.findFirstById(sysPost.getId());
        if (null == newSysPost) {
            throw new RuntimeException("404 NotFound");
        }

        if (null != sysPostRepository.findFirstByPostCodeAndIdNot(
                sysPost.getPostCode(), sysPost.getId())) {
            throw new RuntimeException("岗位编号已存在");
        }

        newSysPost.edit(sysPost);
        newSysPost.setUpdateBy(LoginInfoAccessContext.getLoginInfo().getNickname());
        return sysPostRepository.save(newSysPost);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void del(List<Long> ids) {
        sysPostRepository.deleteAllByIdInBatch(ids);
        sysUserPostRepository.deleteByPostIdIn(ids);
    }

    @Override
    public List<String> getNamesByUserId(long userId) {
        QSysUserPost qSysUserPost = QSysUserPost.sysUserPost;
        QSysPost qSysPost = QSysPost.sysPost;

        return jpaQueryFactory.select(qSysPost.postName)
                .from(qSysPost)
                .where(qSysPost.id.in(
                        JPAExpressions.select(qSysUserPost.postId).from(qSysUserPost).where(qSysUserPost.userId.eq(userId))
                ))
                .orderBy(qSysPost.orderby.asc(), qSysPost.id.desc())
                .fetch();
    }
}
